<?php
class SimpleAuthSvcClient {
	// Requires xmlrpc extension loaded into PHP
	// (unless someone wants to write an xmlrpc request encoder/decoder ;p )
	var $service_host;
	var $service_port;
	var $service_path;
	var $valid_crypt_words;
	
	function SimpleAuthSvcClient($service_host, $service_path, $service_port) {
		$this->service_host = $service_host;
		$this->service_port = $service_port;
		$this->service_path = $service_path;
		$this->valid_crypt_words = array("encrypt", "decrypt");
	}
	
	function auth($auth_method, $username, $password = null, $service_name = null, $role_name = null) {
		$response = false;

		if (strtolower($auth_method) == "authenticate") {
			if ($password == null) {
				return "SimpleAuthSvcClient->call: You must specify a password when using authenticate";
			}
			
			return $this->authenticate($username, $password);
		} elseif (strtolower($auth_method) == "authorize") {
			if ($service_name == null || $role_name == null) {
				$return_string = "";
				if ($service_name == null) {
					$return_string = "SimpleAuthSvcClient->call: You must specify a service name when using authorize";
				}
				
				if ($role_name == null) {
					if (count($return_string) > 0) {
						$return_string .= "<br />";
					}
					$return_string .= "SimpleAuthSvcClient->call: You must specify a role name when using authorize";
				}
				
				return $return_string;
			}
			
			return $this->authorize($service_name, $username, $role_name);
		}
	}
	
	function authenticate($username, $password, $crypt = null, $auth_override = null) {
		$authenticated = false;
		
		if ($crypt != null && !is_array($crypt)) {
			return "SimpleAuthSvcClient->authenticate: 'crypt' must be an array containing the words 'encrypt' or 'decrypt' at index 0, and an encryption method at index 1";
		} elseif ($crypt != null && is_array($crypt)) {
			if (!in_array(strtolower($crypt[0]), $this->valid_crypt_words)) {
				return "SimpleAuthSvcClient->authenticate: First value of 'crypt' must be either 'encrypt' or 'decrypt'";
			}
		}
		
		if ($crypt == null) {
			$crypt = array("", "");
		}
		
		$authenticated = $this->_call("authenticate", array($username, $password, $crypt, $auth_override));
		
		return $authenticated;
	}

	function authorize($service_name, $username, $role_name, $auth_override = null) {
		return $this->_call("authorize", array($service_name, $username, $role_name, $auth_override));
	}
	
	function _call($method, $args) {
		$fHandler = fsockopen($this->service_host, $this->service_port, $err_no, $err_str);
		
		if (!$fHandler) {
			return false;
		}
		
		$request = xmlrpc_encode_request($method, $args);
		$query = sprintf(
			"POST /%s HTTP/1.0\r\nUser-Agent: PHPSimpleAuthSvcClient\r\nHost: %s:%d\r\nContent-Type: text/xml; charset=ISO-8859-1\r\nContent-Length: %d\r\n\r\n%s\r\n",
			$this->service_path,
			$this->service_host,
			$this->service_port,
			strlen($request),
			$request
		);
		
		fwrite($fHandler, $query);
		$output = "";
		while (!feof($fHandler)) {
			$output .= fread($fHandler, 4096);
		}
		fclose($fHandler);
		
		//print $output."<br /><br />\r\n\r\n";
		
		$output = explode("\r\n\r\n", $output);
		$output = xmlrpc_decode($output[1]);
		
		if (strlen($output) < 1)  {
			return false;
		}
		
		return true;
	}
	
}

// Testing
$s = new SimpleAuthSvcClient("10.1.5.54", "RPC2", "11010");

// Direct call to authenticate
if ($s->authenticate("test_user", "test_pass", array("encrypt", "test_md5"))) {
	print "AUTHENTICATED!";
} else {
	print "H4X!";
}

print "<br /><br />";

// Direct call to authorize
if ($s->authorize("test_service", "test_user", "test_role")) {
	print "AUTHORIZED!";
} else {
	print "H4X!";
}

print "<br /><br />";

// Call to managed method - note that this method does not support crypt for authenticate, nor auth_override for both authenticate and authorize
if ($s->auth("authorize", "test_user", null, "test_service", "test_role")) {
	print "AUTHORIZED";
} else {
	print "H4X!";
}
?>